#include"../process.h"
#include"distance_calc.h"
#include"config.h"
#include"../../log/log_mgr.h"
#include"cluster.h"
#include"edge_checker\distance_checker.h"
#include"model\ed_translate_model.h"
#include"model\ngram_lm.h"
#include"model\language_model.h"
#include"model\translate_model.h"
#include"node_reformer\node_reformer.h"
#include"node_reformer\spell_correction.h"
#include"label_selector\freq_selector.h"
#include"label_selector\label_selector.h"
#include"node_reformer\node_reformer.h"
#include"node_reformer\stopwords_removal.h"
#include"node_reformer\abbr_reform.h"
#include"stemmer\porterStemmer.h"
#include"node_reformer\stemmer.h"
#include"node_reformer\term_sorter.h"

void load_seq(iostream *seq_file, vector<string> &sequence)
{
	string line;
	while(!seq_file->eof())
	{
		getline(*seq_file, line);
		sequence.push_back(line);
	}
}

//int main(int argc, const char* argv[])
//{
//	fstream input(argv[1], fstream::in);
//	fstream lang_model(argv[2], fstream::in);
//	fstream trans_model(argv[3], fstream::in);
//	fstream stop_file(argv[4], fstream::in);
//	fstream abbr_file_gt(argv[5], fstream::in);
//	fstream abbr_file_l(argv[6], fstream::in);
//	fstream result(argv[7], fstream::out);
//	fstream seq_file(argv[9], fstream::in);
//
//	fstream conf_file(argv[8], fstream::in);
//	Config::load(&conf_file);
//	conf_file.close();
//
//	DistCalc dist_calc;
//	DistanceChecker distanceChecker(&dist_calc);
//
//	StopwordsRemval stopWordsRemover(&stop_file);
//	stop_file.close();
//
//	AbbrReform abbrReformer(&abbr_file_gt);
//	abbr_file_gt.close();
//
//	CStem stem;
//	Stemmer stemmer(&stem);
//
//	TermSorter term_sorter;
//
//	vector<string> sequence;
//	load_seq(&seq_file, sequence);
//	seq_file.close();
//
//	util::LogMgr::init(argc, argv);
//	util::LogMgr::time_start();
//	string line;
//	string lang_info;
//	string trans_info;
//	string abbr_info;
//	while(!input.eof()){
//		//cout << "read model file\n";
//		getline(input, line);
//		getline(lang_model, lang_info);
//		getline(trans_model, trans_info);
//		getline(abbr_file_l, abbr_info);
//
//		//cout << "build cluster&graph\n";
//		Cluster cluster(line);		
//		for(int i = 0; i < sequence.size(); ++ i)
//		{
//			string action = sequence[i];
//			if(action == "raw_query")
//			{
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);
//			}else
//			if(action == "spell_correction")
//			{
//				//cout << "init spell correction by model file\n";
//				SpellCorrection spellCorrector(lang_info, trans_info, &dist_calc);
//				//cout << "update node by correction\n";
//				cluster.graph.update_node(spellCorrector);
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);
//			}else
//			if(action == "stopwords_removal")
//			{
//				//cout << "remove stopwords of the nodes\n";
//				cluster.graph.update_node(stopWordsRemover);
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);
//			}else
//			if(action == "abbr_reform")
//			{
//				//cout << "change node instance to abbreivation\n";
//				AbbrReform* abbrReformer_cast = dynamic_cast<AbbrReform*>(&abbrReformer);
//				abbrReformer_cast->update(abbr_info);
//				cluster.graph.update_node(abbrReformer);
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);
//			}else
//			if(action == "stemming")
//			{
//				//cout << "stemming\n";
//				cluster.graph.update_node(stemmer);
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);
//			}else
//			if(action == "term_sort")
//			{
//				//cout << "sort terms\n";
//				cluster.graph.update_node(term_sorter);
//				//cout << "add edge by distance\n";
//				cluster.graph.update_edge(distanceChecker);		
//			}
//		}
//		//cout << "export current result with group label\n";
//		cluster.display(&result);
//	}
//
//	util::LogMgr::time_end();
//	util::LogMgr::done();
//	input.close();
//	lang_model.close();
//	trans_model.close();
//	abbr_file_l.close();
//	result.close();
//	return 0;
//}
int main(int argc, const char* argv[])
{
	fstream input(argv[1], fstream::in);
	fstream lang_model(argv[2], fstream::in);
	fstream trans_model(argv[3], fstream::in);
	fstream stop_file(argv[4], fstream::in);
	fstream abbr_file_gt(argv[5], fstream::in);
	fstream abbr_file_l(argv[6], fstream::in);
	fstream result(argv[7], fstream::out);
	fstream seq_file(argv[9], fstream::in);

	fstream conf_file(argv[8], fstream::in);
	Config::load(&conf_file);
	conf_file.close();
	fstream *out_q;
	bool output_q = Config::get("gen_group_label")=="1"? true:false;
	if(output_q)
	{
		string res(argv[7]);
		out_q = new fstream(res + ".query", fstream::out);
	}
	DistCalc dist_calc;
	DistanceChecker distanceChecker(&dist_calc);

	StopwordsRemval stopWordsRemover(&stop_file);
	stop_file.close();

	AbbrReform abbrReformer(&abbr_file_gt);
	abbr_file_gt.close();

	Stemmer stemmer;

	TermSorter term_sorter;

	vector<string> sequence;
	load_seq(&seq_file, sequence);
	seq_file.close();

	util::LogMgr::init(argc, argv);
	util::LogMgr::time_start();
	string line;
	string lang_info;
	string trans_info;
	string abbr_info;
	while(!input.eof()){
		//cout << "read model file\n";
		getline(input, line);
		getline(lang_model, lang_info);
		getline(trans_model, trans_info);
		getline(abbr_file_l, abbr_info);

		//cout << "build cluster&graph\n";
		Cluster cluster(line);
		cluster.graph.update_edge(distanceChecker);
		for(int i = 0; i < sequence.size(); ++ i)
		{
			string action = sequence[i];
			if(action == "raw_query")
			{
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);
			}else
			if(action == "spell_correction")
			{
				//cout << "init spell correction by model file\n";
				SpellCorrection spellCorrector(lang_info, trans_info, &dist_calc);
				//cout << "update node by correction\n";
				cluster.graph.update_node(spellCorrector);
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);
			}else
			if(action == "stopwords_removal")
			{
				//cout << "remove stopwords of the nodes\n";
				cluster.graph.update_node(stopWordsRemover);
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);
			}else
			if(action == "abbr_reform")
			{
				//cout << "change node instance to abbreivation\n";
				AbbrReform* abbrReformer_cast = dynamic_cast<AbbrReform*>(&abbrReformer);
				abbrReformer_cast->update(abbr_info);
				cluster.graph.update_node(abbrReformer);
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);
			}else
			if(action == "stemming")
			{
				//cout << "stemming\n";
				cluster.graph.update_node(stemmer);
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);
			}else
			if(action == "term_sort")
			{
				//cout << "sort terms\n";
				cluster.graph.update_node(term_sorter);
				//cout << "add edge by distance\n";
				cluster.graph.update_edge(distanceChecker);		
			}
		}
		//cout << "export current result with group label\n";
		//cluster.display_with_label(&result, FreqSelector());
		if(output_q)
			cluster.display(&result, out_q, FreqSelector());
		else
			cluster.display(&result);
	}

	util::LogMgr::time_end();
	util::LogMgr::done();
	input.close();
	lang_model.close();
	trans_model.close();
	abbr_file_l.close();
	result.close();
	if(argc > 10)
	{
		fstream succ(argv[10], fstream::out);
		succ.close();	
	}
	if(output_q)
		out_q->close();
	delete []out_q;
	return 0;
}